const express = require('express');
const { body, query } = require('express-validator');
const paymentController = require('../controllers/paymentController');
const { protect, restrictTo } = require('../middleware/auth');
const rateLimit = require('express-rate-limit');

const router = express.Router();

// 限制支付请求的频率
const paymentLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15分钟
  max: 50, // 限制每个IP 15分钟内最多50次请求
  message: {
    status: 'error',
    message: '支付请求过于频繁，请稍后再试'
  },
  standardHeaders: true,
  legacyHeaders: false
});

// 限制创建支付订单的频率
const createPaymentLimiter = rateLimit({
  windowMs: 5 * 60 * 1000, // 5分钟
  max: 10, // 限制每个IP 5分钟内最多10次创建支付请求
  message: {
    status: 'error',
    message: '创建支付订单过于频繁，请稍后再试'
  },
  standardHeaders: true,
  legacyHeaders: false
});

// 限制退款请求的频率
const refundLimiter = rateLimit({
  windowMs: 60 * 60 * 1000, // 1小时
  max: 5, // 限制每个IP 1小时内最多5次退款请求
  message: {
    status: 'error',
    message: '退款请求过于频繁，请稍后再试'
  },
  standardHeaders: true,
  legacyHeaders: false
});

// 验证规则
const createPaymentValidation = [
  body('orderId')
    .isMongoId()
    .withMessage('订单ID格式无效'),
  
  body('paymentMethod')
    .isIn(['alipay', 'wechat'])
    .withMessage('支付方式必须是 alipay 或 wechat')
];

const refundValidation = [
  body('orderId')
    .isMongoId()
    .withMessage('订单ID格式无效'),
  
  body('refundAmount')
    .isFloat({ min: 0.01 })
    .withMessage('退款金额必须大于0.01'),
  
  body('reason')
    .isLength({ min: 1, max: 200 })
    .withMessage('退款原因长度必须在1-200个字符之间')
];

const paymentRecordsValidation = [
  query('page')
    .optional()
    .isInt({ min: 1 })
    .withMessage('页码必须是大于0的整数'),
  
  query('limit')
    .optional()
    .isInt({ min: 1, max: 100 })
    .withMessage('每页数量必须在1-100之间'),
  
  query('paymentMethod')
    .optional()
    .isIn(['alipay', 'wechat'])
    .withMessage('支付方式必须是 alipay 或 wechat'),
  
  query('paymentStatus')
    .optional()
    .isIn(['pending', 'paid', 'failed', 'cancelled'])
    .withMessage('支付状态无效'),
  
  query('startDate')
    .optional()
    .isISO8601()
    .withMessage('开始日期格式无效'),
  
  query('endDate')
    .optional()
    .isISO8601()
    .withMessage('结束日期格式无效')
    .custom((value, { req }) => {
      if (req.query.startDate && value) {
        const endDate = new Date(value);
        const startDate = new Date(req.query.startDate);
        if (endDate <= startDate) {
          throw new Error('结束日期必须晚于开始日期');
        }
      }
      return true;
    })
];

const paymentStatsValidation = [
  query('period')
    .optional()
    .isIn(['7d', '30d', '90d', '1y'])
    .withMessage('统计周期必须是 7d、30d、90d 或 1y')
];

// 应用限流中间件到所有路由
router.use(paymentLimiter);

// 公开路由

/**
 * @route   GET /api/payment/methods
 * @desc    获取支持的支付方式
 * @access  Public
 */
router.get('/methods', paymentController.getPaymentMethods);

/**
 * @route   POST /api/payment/alipay/notify
 * @desc    处理支付宝支付回调
 * @access  Public
 */
router.post('/alipay/notify', paymentController.handleAlipayNotify);

/**
 * @route   POST /api/payment/wechat/notify
 * @desc    处理微信支付回调
 * @access  Public
 */
router.post('/wechat/notify', paymentController.handleWechatNotify);

// 需要认证的路由
router.use(protect);

/**
 * @route   POST /api/payment/create
 * @desc    创建支付订单
 * @access  Private
 */
router.post('/create',
  createPaymentLimiter,
  createPaymentValidation,
  paymentController.createPayment
);

/**
 * @route   GET /api/payment/status/:paymentId
 * @desc    查询支付状态
 * @access  Private
 */
router.get('/status/:paymentId', paymentController.getPaymentStatus);

/**
 * @route   POST /api/payment/refund
 * @desc    申请退款
 * @access  Private
 */
router.post('/refund',
  refundLimiter,
  refundValidation,
  paymentController.requestRefund
);

/**
 * @route   GET /api/payment/records
 * @desc    获取用户支付记录
 * @access  Private
 */
router.get('/records',
  paymentRecordsValidation,
  paymentController.getPaymentRecords
);

/**
 * @route   GET /api/payment/stats
 * @desc    获取支付统计信息
 * @access  Private
 */
router.get('/stats',
  paymentStatsValidation,
  paymentController.getPaymentStats
);

module.exports = router;